package com.sita.cfmoto.ui.view;

import android.animation.Animator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.Shader;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;

import com.sita.cfmoto.R;
import com.sita.cfmoto.utils.LogUtils;

public class RotateMenuView extends View {

    private final String TAG = RotateMenuView.class.getSimpleName();
    // all value here
    private final int SPEED_MAX = 180;
    private final float mMaxValue = SPEED_MAX;
    private OnMenuSelectedListener mMenuListener = null;
    private MENU_STATUS mStatus = MENU_STATUS.STATUS_READY;
    // all Bitmap here
    private Bitmap backBitmap;
    private Bitmap btnNormalBitmap;
    private Bitmap btnPressedBitmap;
    // all paint here
    private Paint mBackPaint;
    private Paint mBtnPaint;
    private RectF mOval;
    private float mAngle = 0f;
    private float mPreAngle = 0f;

    // color here
    private float mCurValue = 0f;
    private float mPreValue = 0f;
    private float mAngleOffset = 22f;
    private float mAngleSweep = 120f;
    private float mScale = 1;
    private long mTime = 0;
    private int mRpm = 0;
    //    private int margin = 0;
    private int mViewWidth = 0;
    private int mXOffset = 0;
    private int mYOffset = 0;
    private int mX0 = 0;

    // string here

    // size here
    private int mY0 = 0;
    private int mXCenter = 0;
    private int mYCenter = 0;
    private int mBtnWidth = 0;
    private float mHardMargin = 25;
    private boolean mIsClickButton = false;
    private int mMaxAngle = 210; // 根据图片的范围调整
    private float mButtonEnableWidth = 140;
    private float mMenuRadius = 160;
    private float mMenuWidth = 70;
    private float mStartAngle = 5;
    private float mIntervalAngle = 40; // 根据图片调整
    private int mAnimatorLong = 800;
    private boolean mIsShow = true;
    private boolean mIsMoving = false;
    //    private boolean mIsLocked = false;
    private boolean mIsClickMenu = false;
    public RotateMenuView(Context context) {
        super(context);
        init();
    }
    public RotateMenuView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public void registerMenuListener(OnMenuSelectedListener listener) {
        this.mMenuListener = listener;
    }

    public void init() {
//        BitmapFactory.Options options = new BitmapFactory.Options();
//        options.inScaled = false;
//        backBitmap = BitmapFactory.decodeResource(getResources(), mIsLocked ? R.drawable.rotate_menu_bg_locked : R.drawable.rotate_menu_bg_unlock, options);
//        btnNormalBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.rotate_menu_button_normal, options);
//        btnPressedBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.rotate_menu_button_selected, options);
//        mBackPaint = new Paint(Paint.ANTI_ALIAS_FLAG);//消除锯齿
//        mBtnPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        loadResource();
    }

//    public void setLocked(boolean locked) {
//        this.mIsLocked = locked;
//        // TODO: 2016/5/6 change the background
//        BitmapFactory.Options options = new BitmapFactory.Options();
//        options.inScaled = false;
//        backBitmap = BitmapFactory.decodeResource(getResources(), (mIsLocked) ?
//                R.drawable.rotate_menu_bg_lock_selected :
//                R.drawable.rotate_menu_bg_unlock_selected, options);
//        this.invalidate();
//    }

    private void loadResource() {
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inScaled = false;
        backBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.rotate_menu_item_1, options);
        btnNormalBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.rotate_menu_button_off, options);
        btnPressedBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.rotate_menu_button_on, options);
        mBackPaint = new Paint(Paint.ANTI_ALIAS_FLAG);//消除锯齿
        mBtnPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    }

    @Override
    public boolean performClick() {
        if (mIsMoving) {
            return true; // // TODO: 2016/3/1 need to double check;
        }

        if (mStatus == MENU_STATUS.STATUS_NORMAL) {
            mStatus = MENU_STATUS.STATUS_PRESSED;
            this.invalidate();
        } else if (mStatus == MENU_STATUS.STATUS_OPENING) {
//            mStatus = SPEED_STATUS.SPEED_STATUS_PAUSED; // // TODO: 2016/3/1
        }
        return super.performClick();
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {

        if (mStatus == MENU_STATUS.STATUS_OPENING || mStatus == MENU_STATUS.STATUS_CLOSING) {

        } else if (mStatus != MENU_STATUS.STATUS_OPENING) {
            // check click button
            try {
                float dx = Math.abs((int) event.getX() - mXCenter);
                float dy = Math.abs((int) event.getY() - mYCenter);

                // check click center button
                if (dx < mButtonEnableWidth * mScale / 2f && dy < mButtonEnableWidth * mScale / 2f) {
                    clickButton();
                }

                for (int i = 0; i < 4; i++) {
                    double radius = Math.toRadians(mStartAngle + (float) i * mIntervalAngle);
                    double xCenter = (double) mXCenter - (double) mMenuRadius * mScale * Math.cos(radius);
                    double yCenter = (double) mYCenter - (double) mMenuRadius * mScale * Math.sin(radius);

                    dx = Math.abs(event.getX() - (float) xCenter);
                    dy = Math.abs(event.getY() - (float) yCenter);

                    if (dx < mMenuWidth * mScale / 2 && dy < mMenuWidth * mScale / 2) {
                        switch (i) {
                            case 0:
                                clickItem1();
                                break;
                            case 1:
                                clickItem2();
                                break;
                            case 2:
                                clickItem3();
                                break;
                            case 3:
                                clickItem4();
                                break;
                            default:
                                break;
                        }
                        break;
                    }
                }


            } catch (IllegalArgumentException exception) {

            }
        }

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                Log.d(TAG, "onTouchEvent: down");
                break;
            case MotionEvent.ACTION_UP:
                Log.d(TAG, "onTouchEvent: up");
                if (mIsClickMenu) {
                    releaseClick();
                }
                break;
            case MotionEvent.ACTION_MOVE:
                Log.d(TAG, "onTouchEvent: move");
                break;
            case MotionEvent.ACTION_CANCEL:
                break;
            default:
                break;
        }

        return super.onTouchEvent(event);
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        getParent().requestDisallowInterceptTouchEvent(true);
        return super.dispatchTouchEvent(ev);
    }

    // draw start page
    private void onDrawReady(Canvas canvas) {
        // only button
        Log.d(TAG, "onDrawReady: ");
        _drawButton(canvas, btnNormalBitmap);
        canvas.save();
    }

    private void _drawButton(Canvas canvas, Bitmap btnBitmap) {
        mBtnWidth = (int) ((float) (btnBitmap.getWidth()) * mScale);
        RectF dst = new RectF(mXCenter - mBtnWidth / 2, mYCenter - mBtnWidth / 2, mXCenter + mBtnWidth / 2, mYCenter + mBtnWidth / 2);
        canvas.drawBitmap(btnBitmap, null, dst, mBtnPaint);
    }

    private void onDrawRunning(Canvas canvas) {
        Log.d(TAG, "onDrawRunning: ");

        // start page background
        _drawButton(canvas, btnPressedBitmap);
        canvas.save();

        Shader shader = new BitmapShader(backBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);//CLAMP 拉伸
        Matrix localMatrix = new Matrix();
        localMatrix.postScale(mScale, mScale);
        localMatrix.postTranslate(mXOffset, mYOffset);
        shader.setLocalMatrix(localMatrix);
        mBackPaint.setShader(shader);
        mOval = new RectF(0, 0, mViewWidth, mViewWidth);
        mOval.offset(mXOffset, mYOffset);

        // progress
        float startAngle = mAngleOffset + mAngleSweep;
        canvas.drawArc(mOval, startAngle, mAngle, true, mBackPaint);

    }

    @Override
    protected void onDraw(Canvas canvas) {
        if (!mIsShow) {
            return;
        }

        int width = getWidth();
        int height = getHeight();
        mViewWidth = (width < height) ? width : height;

        mXOffset = (width - mViewWidth) / 2;
        mYOffset = height - mViewWidth; // align parent bottom
        mScale = (float) mViewWidth / (float) backBitmap.getWidth();

        mX0 = mXOffset;
        mY0 = mYOffset;

        mXCenter = mViewWidth / 2 + mXOffset;
        mYCenter = mViewWidth / 2 + mYOffset;

        LogUtils.i(TAG, "onDraw " + "w=" + width + ", h=" + height);

        if (mStatus == MENU_STATUS.STATUS_READY) {
            onDrawReady(canvas);
        } else if (mStatus == MENU_STATUS.STATUS_OPENING || mStatus == MENU_STATUS.STATUS_CLOSING) {
            onDrawRunning(canvas);
        } else if (mStatus == MENU_STATUS.STATUS_SELECTED) {
            onDrawRunning(canvas);
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
        int viewWidthHeight = widthSize > heightSize ? heightSize : widthSize;
        setMeasuredDimension(viewWidthHeight, viewWidthHeight);
        LogUtils.i(TAG, "onMeasure " + "w=" + viewWidthHeight + ", h=" + viewWidthHeight);
    }

    private void clickButton() {
        LogUtils.d(TAG, "click button");
        if (mStatus == MENU_STATUS.STATUS_READY) {
            mStatus = MENU_STATUS.STATUS_OPENING;
//            startOpenning();
            startOpen();
            // 恢复背景图片
            BitmapFactory.Options options = new BitmapFactory.Options();
            options.inScaled = false;
            backBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.rotate_menu_item_1, options);

            if (mMenuListener != null) {
                mMenuListener.onSelected(MENU_ITEM.MENU_OPEN);
            }
        } else if (mStatus == MENU_STATUS.STATUS_SELECTED) {
            mStatus = MENU_STATUS.STATUS_CLOSING;
//            startClosing();
            startClose();
            if (mMenuListener != null) {
                mMenuListener.onSelected(MENU_ITEM.MENU_CLOSED);
            }
        }
    }

    private void clickItem4() {
        mIsClickMenu = true;
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inScaled = false;
        backBitmap = BitmapFactory.decodeResource(getResources(),
                R.mipmap.rotate_menu_item_4, options);
        invalidate();
        if (mMenuListener != null) {
            mMenuListener.onSelected(MENU_ITEM.ITEM_4);
        }
    }

    private void clickItem1() {
        mIsClickMenu = true;
//        mIsLocked = !mIsLocked;
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inScaled = false;
        backBitmap = BitmapFactory.decodeResource(getResources(),
                R.mipmap.rotate_menu_item_1, options);
        invalidate();
        if (mMenuListener != null) {
            mMenuListener.onSelected(MENU_ITEM.ITEM_1);
        }
    }

    private void clickItem2() {
        mIsClickMenu = true;
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inScaled = false;
        backBitmap = BitmapFactory.decodeResource(getResources(),
                R.mipmap.rotate_menu_item_2, options);
        invalidate();
        if (mMenuListener != null) {
            mMenuListener.onSelected(MENU_ITEM.ITEM_2);
        }
    }

    private void clickItem3() {
        mIsClickMenu = true;
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inScaled = false;
        backBitmap = BitmapFactory.decodeResource(getResources(),
                R.mipmap.rotate_menu_item_3, options);
        invalidate();
        if (mMenuListener != null) {
            mMenuListener.onSelected(MENU_ITEM.ITEM_3);
        }
    }

    private void releaseClick() {
        mIsClickMenu = false;
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inScaled = false;
        backBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.rotate_menu_item_1, options);
        invalidate();
    }

    private void startOpenning() {
        startAnimator(0, mMaxAngle);
    }

    private void startClosing() {
        startAnimator(mMaxAngle, 0);
    }

    private void startOpen() {
        mAngle = mMaxAngle;
        mStatus = MENU_STATUS.STATUS_SELECTED;
        invalidate();
//        if (mStatus == MENU_STATUS.STATUS_OPENING) {
//
//        } else if (mStatus == MENU_STATUS.STATUS_CLOSING) {
//            mStatus = MENU_STATUS.STATUS_READY;
//        }
    }

    private void startClose() {
        mAngle = mMaxAngle;
        mStatus = MENU_STATUS.STATUS_READY;
        invalidate();
    }

    private void startAnimator(int start, int end) {
        this.mPreValue = start;
        this.mCurValue = end;

        // add animator here
        ValueAnimator animator = ValueAnimator.ofFloat(mPreValue, mCurValue);
        if ((mPreValue > mCurValue)) {
            animator.setInterpolator(new DecelerateInterpolator());
        } else {
            animator.setInterpolator(new AccelerateInterpolator());
        }
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            public void onAnimationUpdate(ValueAnimator animation) {
                float value = (Float) animation.getAnimatedValue();
                mAngle = value;
                invalidate();
            }
        });
        animator.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {

            }

            @Override
            public void onAnimationEnd(Animator animation) {
                LogUtils.d(TAG, "animator end");
                if (mStatus == MENU_STATUS.STATUS_OPENING) {
                    mStatus = MENU_STATUS.STATUS_SELECTED;
                } else if (mStatus == MENU_STATUS.STATUS_CLOSING) {
                    mStatus = MENU_STATUS.STATUS_READY;
                }
            }

            @Override
            public void onAnimationCancel(Animator animation) {

            }

            @Override
            public void onAnimationRepeat(Animator animation) {

            }
        });
        animator.setDuration(mAnimatorLong);
        animator.start();
    }

    public void setTime(long time) {
        this.mTime = time;
        invalidate();
    }

    public void setRpm(int rpm) {
        this.mRpm = rpm;
    }

    private float getAngle() {
        return (mCurValue / mMaxValue) * (360f - mAngleSweep);
    }

    private float getAngle(float value) {
        return (value / mMaxValue) * (360f - mAngleSweep);
    }

    public MENU_STATUS getSpeedStatus() {
        return mStatus;
    }

    private void resetData() {
        mAngle = 0f;
        mPreAngle = 0f;
        mCurValue = 0f;
        mPreValue = 0f;
    }

    public void setMove(boolean isMove) {
        mIsMoving = isMove;
    }

    public enum MENU_STATUS {
        STATUS_READY,
        STATUS_OPENING,
        STATUS_CLOSING,
        STATUS_NORMAL,
        STATUS_PRESSED,
        STATUS_SELECTED
    }

    public enum MENU_ITEM {
        ITEM_1,
        ITEM_2,
        ITEM_3,
        ITEM_4,
        ITEM_5,
        MENU_CLOSED,
        MENU_OPEN
    }

    public interface OnMenuSelectedListener {
        public void onSelected(MENU_ITEM item);
    }
}